package ly.count.ohos.sdk;

public class ModuleSessions extends ModuleBase {
    private static final double RANDOM_NUM = 1000000000d;
    boolean isManualSessionControlEnabled = false;
    long prevSessionDurationStartTime = 0L;

    final Sessions sessionInterface;

    ModuleLog moduleLog;

    ModuleSessions(Countly cly, CountlyConfig config) {
        super(cly);

        moduleLog = cly.L;

        moduleLog.v("[ModuleSessions] Initialising");

        isManualSessionControlEnabled = config.manualSessionControlEnabled;
        mCly.disableUpdateSessionRequests_ = config.disableUpdateSessionRequests;

        sessionInterface = new Sessions();
    }

    void beginSessionInternal() {
        moduleLog.d("[ModuleSessions] 'beginSessionInternal'");

        prevSessionDurationStartTime = System.nanoTime();
        mCly.connectionQueue_.beginSession(mCly.moduleLocation.isLocationDisabled,
                mCly.moduleLocation.locationCountryCode,
                mCly.moduleLocation.locationCity,
                mCly.moduleLocation.locationGpsCoordinates,
                mCly.moduleLocation.locationIpAddress);
    }

    void updateSessionInternal() {
        moduleLog.d("[ModuleSessions] 'updateSessionInternal'");

        if (!mCly.disableUpdateSessionRequests_) {
            mCly.connectionQueue_.updateSession(roundedSecondsSinceLastSessionDurationUpdate());
        }
    }

    /**
     * endSessionInternal
     *
     * @param deviceIdOverride used when switching deviceID to a different one and ending the previous session
     */
    void endSessionInternal(String deviceIdOverride) {
        moduleLog.d("[ModuleSessions] 'endSessionInternal'");

        mCly.connectionQueue_.endSession(roundedSecondsSinceLastSessionDurationUpdate(), deviceIdOverride);
        prevSessionDurationStartTime = 0;

        mCly.sendEventsIfExist();
    }

    /**
     * Calculates the unsent session duration in seconds, rounded to the nearest int.
     *
     * @return int类型的round
     */
    int roundedSecondsSinceLastSessionDurationUpdate() {
        final long currentTimestampInNanoseconds = System.nanoTime();
        final long unsentSessionLengthInNanoseconds = currentTimestampInNanoseconds - prevSessionDurationStartTime;
        prevSessionDurationStartTime = currentTimestampInNanoseconds;
        return (int) Math.round(unsentSessionLengthInNanoseconds / RANDOM_NUM);
    }

    @Override
    void halt() {
        prevSessionDurationStartTime = 0;
    }

    public class Sessions {
        public void beginSession() {
            synchronized (mCly) {
                if (!mCly.isInitialized()) {
                    moduleLog.e("Countly.sharedInstance().init must be called before beginSession");
                    return;
                }

                moduleLog.i("[Sessions] Calling 'beginSession', manual session control enabled:["
                        + isManualSessionControlEnabled + "]");

                if (!isManualSessionControlEnabled) {
                    moduleLog.w("[Sessions] 'beginSession' "
                            + "will be ignored since manual session control is not enabled");
                    return;
                }

                beginSessionInternal();
            }
        }

        public void updateSession() {
            synchronized (mCly) {
                if (!mCly.isInitialized()) {
                    moduleLog.e("Countly.sharedInstance().init must be called before updateSession");
                    return;
                }

                moduleLog.i("[Sessions] Calling 'updateSession', manual session control enabled:["
                        + isManualSessionControlEnabled + "]");

                if (!isManualSessionControlEnabled) {
                    moduleLog.w("[Sessions] 'updateSession' "
                            + "will be ignored since manual session control is not enabled");
                    return;
                }

                moduleLog.i("[Sessions] Calling 'updateSession'");

                updateSessionInternal();
            }
        }

        public void endSession() {
            synchronized (mCly) {
                if (!mCly.isInitialized()) {
                    moduleLog.e("Countly.sharedInstance().init must be called before endSession");
                    return;
                }

                moduleLog.i("[Sessions] Calling 'endSession', manual session control enabled:["
                        + isManualSessionControlEnabled + "]");

                if (!isManualSessionControlEnabled) {
                    moduleLog.w("[Sessions] 'endSession' will be ignored since manual session control is not enabled");
                    return;
                }

                endSessionInternal(null);
            }
        }
    }
}
